package com.nav.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JSON {
	private static int i;
	public static Map<String, Object> parseObject(String s) throws Exception {
		i = 0;
		return parseObject(s.toCharArray());
	}
	private static Map<String, Object> parseObject(char c[]) throws Exception {
		Map<String, Object> m = new HashMap<String, Object>();
		assert(c[i] == '{');
		i++;
		do {
			String key = parseString(c);
			assert(c[i]== ':');
			i++;
			Object value = parseValue(c);
			m.put(key, value);
		} while(c[i++] == ',');
		assert(c[i - 1] == '}');
		return m;
	}
	private static Object[] parseArray(char c[]) throws Exception {
		List<Object> l = new ArrayList<Object>();
		assert(c[i] == '[');
		i++;
		do {
			l.add(parseValue(c));
		} while(c[i++] == ',');
		assert(c[i - 1] == ']');
		Object[] r = new Object[l.size()];
		return l.toArray(r);
	}
	private static double parseNumber(char c[]) {
		StringBuilder s = new StringBuilder();
		if(c[i] == '-') {
			s.append("-");
			i++;
		}
		if(c[i] == '0') {
			s.append("0");
			i++;
		} else if(c[i] >= '1' && c[i] <= '9') {
			s.append(c[i++]);
			while(c[i] >= '1' && c[i] <= '9')
				s.append(c[i++]);
		}
		if(c[i] == '.') {
			s.append('.');
			i++;
			while(c[i] >= '0' && c[i] <= '9')
				s.append(c[i++]);
		}
		if(c[i] == 'e' || c[i] == 'E') {
			s.append(c[i++]);
			if(c[i] == '+' || c[i] == '-')
				s.append(c[i++]);
			while(c[i] >= '0' && c[i] <= '9')
				s.append(c[i++]);
		}
		return Double.parseDouble(s.toString());
	}
	private static Object parseValue(char c[]) throws Exception {
		int j = i;
		if(c[i] == '"')
			return parseString(c);
		if(c[i] == '{')
			return parseObject(c);
		if(c[i] == '[')
			return parseArray(c);
		if(c[i] == '-' || c[i] >= '0' && c[i] <= '9')
			return parseNumber(c);
		if(c[i] == 't' && c[i + 1] == 'r' && c[i + 2] == 'u' && c[i + 3] == 'e') {
			i += 4;
			return Boolean.TRUE;
		}
		if(c[i] == 'f' && c[i + 1] == 'a' && c[i + 2] == 'l' && c[i + 3] == 's' && c[i + 4] == 'e') {
			i += 5;
			return Boolean.FALSE;
		}
		if(c[i] == 'n' && c[i + 1] == 'u' && c[i + 2] == 'l' && c[i + 3] == 'l') {
			i += 4;
			return null;
		}
		throw new Exception("Unidentified value at " + j);
	}
	private static String parseString(char c[]) {
		StringBuilder s = new StringBuilder();
		assert(c[i] == '\"');
		i++;
		boolean e = false;
		while(e || c[i] != '"') {
			if(e) {
				switch(c[i]) {
				case 'b':
					s.append("\b");
					break;
				case 'f':
					s.append('\f');
					break;
				case 'n':
					s.append('\n');
					break;
				case 'r':
					s.append('\r');
					break;
				case 't':
					s.append('\t');
					break;
				case 'u':
					// TODO
					break;
				default:
					s.append(c[i]);
				}
				e = false;
				i++;
				continue;
			}
			if(c[i] == '\\')
				e = true;
			else
				s.append(c[i]);
			i++;
		}
		i++;
		return s.toString();
	}
	public static void main(String[] args) throws Exception {
		Map<String, Object> m = JSON.parseObject("{\"city\":\"newyork\",\"category\":\"cell-phones\",\"section\":\"for-sale\",\"heading\":\"New batteries C-S2 for Blackberry 7100/7130/8700/Curve/Pearl\"}");
		System.out.println(m);
	}
}
